#ifndef TEMPLE_UTIL_LOGGER_H_
#define TEMPLE_UTIL_LOGGER_H_

#include "util/stdc.h"
namespace util {

class Logger
{
public:
	Logger()
    {
        file = NULL;
        stdio = true;
    }

	~Logger()
    {
        close();
    }

	int open(const string &path, int level, bool stdio)
	{
        file = fopen(path.c_str(), "ab");
        if (!file)
            return 1;

        this->level = level;
        this->stdio = stdio;
        return 0;
    }

	void close()
    {
        if (file)
        {
            fclose(file);
            file = NULL;
        }
    }

    void set_level(int level)
    {
        level=level;
    }

    static void log_sys(const string &ident, const char *format, ...)
    {
        #ifdef WIN32

        va_list args;
        va_start(args, format);
        vprintf(format, args);
        va_end(args);

        #else //WIN32

        va_list args;
        va_start(args, format);
        openlog(ident.c_str(), LOG_CONS | LOG_PID, LOG_USER);
        vsyslog(LOG_INFO, format, args);
        closelog();
        va_end(args);

        #endif //WIN32
    }

    void log_fatal(const string &tag, const char *format, ...)	//0
    {
        if (level < 0)
            return;

        va_list args;
        va_start(args, format);
        write(0, "FATAL", tag.c_str(), format, args);
        va_end(args);
    }

    void log_emerg(const string &tag, const char *format, ...)	//1
    {
        if (level < 1)
            return;

        va_list args;
        va_start(args, format);
        write(1, "EMERG", tag.c_str(), format, args);
        va_end(args);
    }

    void log_alert(const string &tag, const char *format, ...)	//2
    {
        if (level < 2)
            return;

        va_list args;
        va_start(args, format);
        write(2, "ALERT", tag.c_str(), format, args);
        va_end(args);
    }

    void log_error(const string &tag, const char *format, ...)	//3
    {
        if (level < 3)
            return;

        va_list args;
        va_start(args, format);
        write(3, "ERROR", tag.c_str(), format, args);
        va_end(args);
    }

    void log_warn(const string &tag, const char *format, ...)	//4
    {
        if (level < 4)
            return;

        va_list args;
        va_start(args, format);
        write(4, "WARN", tag.c_str(), format, args);
        va_end(args);
    }

    void log_notice(const string &tag, const char *format, ...) //5
    {
        if (level < 5)
            return;

        va_list args;
        va_start(args, format);
        write(5, "NOTIC", tag.c_str(), format, args);
        va_end(args);
    }

    void log_info(const string &tag, const char *format, ...)	//6
    {
        if (level < 6)
            return;

        va_list args;
        va_start(args, format);
        write(6, "INFO", tag.c_str(), format, args);
        va_end(args);
    }

    void log_debug(const string &tag, const char *format, ...)	//7
    {
        if (level < 7)
            return;

        va_list args;
        va_start(args, format);
        write(7, "DEBUG", tag.c_str(), format, args);
        va_end(args);
    }

private:
    FILE *file;
    int level;
    bool stdio;

    void write(int level, const char *title, const char *tag, const char *fmt, va_list args)
    {
        if (!stdio && !file)
            return;

        char buf[4096];
        int ret;

        char *ptr = buf;
        int len = sizeof(buf);

        time_t cur = time(NULL);
        ret = strftime(ptr, len, "\n%m%d:%H%M%S ", localtime(&cur));
        ptr += ret;
        len -= ret;

        ret = snprintf(ptr, len, "%5s [%s]: ", title, tag);
        ptr += ret;
        len -= ret;

        ret = vsnprintf(ptr, len, fmt, args);

        if (stdio)
		{
            puts(buf);
		}

        if (file)
		{
            fputs(buf, file);
			fflush(file);
		}
    }
};

}
#endif //TEMPLE_UTIL_LOGGER_H_
